#pragma once

#include <cstdlib>
#include"SystemCall.hpp"

namespace FixSizeMemoryPoolModule
{
    using namespace SystemCallModule;

    //定长内存池的实现
    template <typename T>
    class FixSizeMemoryPool
    {
    public:
        T* New()
        {
            T* obj = nullptr;
            if (_freelist)
            {
                // 如果自由链表中存在销毁的结点就直接使用
                obj = (T*)_freelist;
                _freelist = *((void**)_freelist);
            }
            else
            {
                // 从 _memory 中获取资源
                if (_leftsize < sizeof(T))
                {
                    // 当前剩余空间不足就会申请内存
                    _leftsize = 128 * 1024;
                    // 这里使用的还是malloc接口，效率已经提高了一些，但是我们可以使用系统调用来完成
                    //_memory = (char *)malloc(_leftsize);
                    // 系统调用实现
                    _memory = (char*)SystemAlloc(_leftsize>>13);
                    if (_memory == nullptr)
                    {
                        assert(false);
                    }
                }
                // 申请内存空间
                obj = (T*)_memory;
                // 至少要存储一个指针的大小
                int objsize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T);
                _memory += objsize;
                _leftsize -= objsize;
            }
            if (obj == nullptr)
            {
                int i = 1;
            }
            // 定位new初始化
            new (obj) T;

            return obj;
        }
        void Delete(T* obj)
        {
            // 显示调用析构函数
            obj->~T();
            // 头插法插入
            // void**强转后解引用可以使得每个平台都兼容
            *((void**)obj) = _freelist;
            _freelist = obj;
        }

    private:
        char* _memory = nullptr;   // 指向内存池的指针(char*方便进行加减操作)
        int _leftsize = 0;         // 剩余的内存空间大小
        void* _freelist = nullptr; // 用于回收内存的自由链表
    };
}
